package com.tanhua.app.service;

import cn.hutool.core.collection.CollUtil;
import com.tanhua.api.service.MovementApi;
import com.tanhua.api.service.UserInfoApi;
import com.tanhua.api.service.VisitorsApi;
import com.tanhua.app.Interceptor.UserHolder;
import com.tanhua.app.exception.BusinessException;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.model.mongo.Movement;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.pojo.UserInfo;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.MovementsVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.VisitorsVo;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class MovementService {

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @DubboReference
    private MovementApi movementApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private VisitorsApi visitorsApi;

    // 动态数据的发布
    public void saveMovements(Movement movement, MultipartFile[] imageContent) {

        // 判断用户数据是否为空
        if (movement == null || StringUtils.isBlank(movement.getTextContent())) {
            throw new BusinessException(ErrorResult.contentError());
        }

        // 将图片文件发布到阿里云上
        List<String> medias = new ArrayList<>();
        try {
            for (MultipartFile file : imageContent) {
                String upload = ossTemplate.upload(file.getOriginalFilename(), file.getInputStream());
                medias.add(upload);
            }

        } catch (IOException e) {
            // 发送失败， 结束方法
            throw new BusinessException(ErrorResult.uploadError());
        }

        // 保存动态数据,分装数据
        movement.setCreated(new Date().getTime());
        movement.setUserId(UserHolder.getUserId());
        movement.setMedias(medias);

        // 根据好友列表数据保存时间线数据
        movementApi.saveMovement(movement);

    }

    // 查询我的动态
    public PageResult<MovementsVo> findPageUserId(Integer page, Integer pagesize, Long userId) {
        // 判断用户id是否有值，没有值使用当前用的id
        if (userId == null) {
            userId = UserHolder.getUserId();
        }

        // 根据当前用户分页查询，用户的动态数据
        PageResult<Movement> pages = movementApi.findByPageUserId(page, pagesize, userId);

        List<Movement> movementList = pages.getItems();

        List<MovementsVo> voList = new ArrayList<>();
        // 遍历动态集合，获取每条动态发布者详细的信息
        for (Movement movement : movementList) {

            // 根据用户id查询，用户的详细信息
            UserInfo userInfo = userInfoApi.findById(movement.getUserId());

            // 分装数据
            MovementsVo vo = MovementsVo.init(userInfo, movement);

            voList.add(vo);
        }


        // 封装结果集
        return new PageResult<>(pages.getPage(), pages.getPagesize(), pages.getCounts(), voList);

    }

    // 查询好友的动态
    public PageResult<MovementsVo> findFriendMovement(Integer page, Integer pagesize) {

        // 获取当前用户id
        Long userId = UserHolder.getUserId();

        // 分页查询，获取动态数据
        List<Movement> movementList = movementApi.findByFriendIdMovement(page, pagesize, userId);

        return getPageResult(movementList, page, pagesize);
    }

    private PageResult<MovementsVo> getPageResult(List<Movement> movementList, Integer page, Integer pagesize) {
        // 判断是好友列表是否为空
        if (movementList == null || movementList.isEmpty()) {
            return new PageResult<>(page, pagesize, 0, null);
        }

        // 抽取用户id
        List<Long> ids = movementList.stream().map(Movement::getUserId).collect(Collectors.toList());

        // 更具ids查询用户详情表
        List<UserInfo> userInfoList = userInfoApi.findByIds(ids);

        Map<Long, UserInfo> map = userInfoList.stream().collect(Collectors.toMap(UserInfo::getId, Function.identity()));

        List<MovementsVo> list = new ArrayList<>();

        // 遍历动态列表
        for (Movement movement : movementList) {
            MovementsVo vo = MovementsVo.init(map.get(movement.getUserId()), movement);

            String key = Constants.MOVEMENTS_INTERACT_KEY + movement.getId().toHexString();

            // 从redis中获取是否点赞的数据
            String hashKeyLike = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
            if (redisTemplate.opsForHash().hasKey(key, hashKeyLike)) {
                vo.setHasLiked(1);
            }

            // 从redis中获取是否喜欢
            String hashKeyLove = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
            if (redisTemplate.opsForHash().hasKey(key, hashKeyLove)) {
                vo.setHasLoved(1);
            }

            list.add(vo);
        }

        return new PageResult<>(page, pagesize, 0, list);
    }

    // 查询推荐动态
    public PageResult<MovementsVo> findRecommendMovements(Integer page, Integer pagesize) {

        // 从redis中获取数据
        String redisKey = Constants.MOVEMENTS_RECOMMEND + UserHolder.getUserId();
        String pids = redisTemplate.opsForValue().get(redisKey);

        // 判断数据是否存在
        List<Movement> list = new ArrayList<>();
        if (StringUtils.isBlank(pids)) {
            // 不存在，随机生成10条动态数据
            list = movementApi.randomMovements(pagesize);
        } else {
            // 存在，处理pid数据
            String[] values = pids.split(",");
            // 对数组数据进行分页
            if ((page - 1) * pagesize < values.length) {
                List<Long> collect = Arrays.stream((values))
                        .skip((page - 1) * pagesize)
                        .limit(pagesize)
                        .map(Long::parseLong)
                        .collect(Collectors.toList());

                // 根据pid数组查询数据
                list = movementApi.findByPids(collect);
            }
        }

        return getPageResult(list, page, pagesize);

    }

    // 根据动态id查询
    public MovementsVo findMovementById(String movementId) {

        // 根据id查询动态信息
        Movement movement = movementApi.findById(movementId);

        // 判断
        if (movement != null && StringUtils.isNotBlank(movement.getTextContent())) {
            // 有动态数据分装
            // 根据用户id查需，用户详情数据
            UserInfo userInfo = userInfoApi.findById(movement.getUserId());
            return MovementsVo.init(userInfo, movement);
        } else {
            return null;
        }

    }

    // 谁看过我
    public List<VisitorsVo> findVisitors() {

        // 查询redis，获取访问时间
        String key = Constants.VISITORS_USER;
        String hashKey = UserHolder.getUserId().toString();
        String date = (String) redisTemplate.opsForHash().get(key, hashKey);

        // 查询用户id,Visitors所有的访客数据
        List<Visitors> visitorsList = visitorsApi.findByUserId(UserHolder.getUserId(), date);

        if (CollUtil.isEmpty(visitorsList)) {
            return new ArrayList<>();
        }

        // 根据列表获取所有的来访用户id
        List<Long> ids = visitorsList.stream().map(Visitors::getVisitorUserId).collect(Collectors.toList());

        // 根据用户列表id,查询用户的详细信息
        Map<Long, UserInfo> map = userInfoApi.findByIds(ids).stream().collect(Collectors.toMap(UserInfo::getId, Function.identity()));

        // 封装数据
        List<VisitorsVo> list = new ArrayList<>();
        for (Visitors visitors : visitorsList) {
            UserInfo userInfo = map.get(visitors.getVisitorUserId());
            if (userInfo != null) {
                VisitorsVo vo = VisitorsVo.init(userInfo, visitors);

                list.add(vo);
            }
        }

        return list;
    }
}
